﻿/// <Summary> 
/// $Author: Nikhil Chinchwade 
/// This file contains the core GUI classes for AzureMonitoringStudio

/// This file uses a graphing control from Codeplex (DynamicDataDisplay). 
/// As per the Licensing terms of DynamicDataDisplay this file is under the license Microsoft Reciprocal License (Ms-RL)
/// 
/// Microsoft Reciprocal License (Ms-RL)

/// This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.

/// 1. Definitions

/// The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law.

/// A "contribution" is the original software, or any additions or changes to the software.

/// A "contributor" is any person that distributes its contribution under this license.

/// "Licensed patents" are a contributor's patent claims that read directly on its contribution.

/// 2. Grant of Rights

/// (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.

/// (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.

/// 3. Conditions and Limitations

/// (A) Reciprocal Grants- For any file you distribute that contains code from the software (in source code or binary format), you must provide recipients the source code to that file along with a copy of this license, which license will govern that file. You may license other files that are entirely your own work and do not contain code from the software under any terms you choose.

/// (B) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.

/// (C) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.

/// (D) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.

/// (E) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.

/// (F) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. 
/// </summary>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Research.DynamicDataDisplay;
using Microsoft.Research.DynamicDataDisplay.DataSources;
using MindTree.PerfWorkbench.Azure.Monitor.AzureMonLib;
using MindTree.PerfWorkbench.Azure.Monitor.CommandLib;
using MindTree.PerfWorkbench.Azure.Monitor.Core;
using System.Threading;
using System.Timers;
using System.Windows.Threading;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using System.IO;

namespace MindTree.PerfWorkbench.Azure.Monitor.AzureMonitor
{
    /// <summary>
    /// Azure Monitoring Studio
    /// </summary>
    public partial class AzureMonStudio : Window
    {        
        private bool IsConnected = false;

        private static DispatcherTimer timer;

        private GraphEntity graph = null ; 

        /// <summary>
        /// Default Constructor
        /// </summary>
        public AzureMonStudio()
        {
            InitializeComponent();
            Focus();
        }

        public bool IsExportChecked
        {
            get
            {
                return AzureMonInstanceContext.IsExportChecked;
            }
            set
            {
                AzureMonInstanceContext.IsExportChecked = value;
            }
        }
        
        /// <summary>
        /// Create a Graph series for the given Performance counter
        /// </summary>
        /// <param name="paramCounter">Performance Counter object</param>
        /// <returns>GraphSeries object</returns>
        private GraphSeries CreatePerformanceGraph(PerfCounter paramCounter)
        {
            PerformanceData data = new PerformanceData(paramCounter);

            var filteredData = new FilteringDataSource<PerformanceInfo>(data, new MaxSizeFilter());

            var ds = new EnumerableDataSource<PerformanceInfo>(data);
            ds.SetXMapping(pi => dateAxis.ConvertToDouble( pi.Time ) );//TimeOfDay.TotalSeconds);
            ds.SetYMapping(pi => pi.Value);

            LineGraph chart = plotter.AddLineGraph(ds, 2.0, String.Format("{0} - {1} - {2} ", paramCounter.MachineName, paramCounter.Category, paramCounter.CounterName));
            
            //chart.DataChanged += chart_DataChanged;
            return new GraphSeries(data, chart);
        }

        public void chart_DataChanged(object sender, EventArgs args)
        {
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            
        }


        /// <summary>
        /// Refresh the graph
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void Refresh(object sender, EventArgs args)
        {          

            PerfResultDataSource.AsyncMethodCaller caller = new PerfResultDataSource.AsyncMethodCaller(PerfResultDataSource.Instance.GetNext);
            //IAsyncResult res = caller.BeginInvoke(null, null);
            
            Dispatcher.BeginInvoke(caller, null);
            //PerfResultDataSource.Instance.GetNext();
        }

        private void test_Selected(object sender, RoutedEventArgs e)
        {

        }

        /// <summary>
        /// Event handler for RolesView_Expanded 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RolesView_Expanded(object sender, RoutedEventArgs e)
        {
            TreeViewItem _item = e.OriginalSource as TreeViewItem;
            _item.IsSelected = true;

            //Expander _expander = _item.FindVisualChild<Expander>();
            //_expander.IsExpanded = true;
        }

        /// <summary>
        /// Event Handler for RolesView_Collapsed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RolesView_Collapsed(object sender, RoutedEventArgs e)
        {
            TreeViewItem _item = e.OriginalSource as TreeViewItem;
            _item.IsSelected = true;
            //Expander _expander = _item.FindVisualChild<Expander>();
            //_expander.IsExpanded = false;
        }              


        /// <summary>
        /// Connect to a Azuer deployment
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Connect_MouseDown(object sender, MouseButtonEventArgs e)
        {
            //StorageCredentialsAccountAndKey storageCredentialsAccountAndKey = new StorageCredentialsAccountAndKey("", "");
            //CloudBlobClient cloudBlobClient = new CloudBlobClient("https://blob.core.windows.net", storageCredentialsAccountAndKey);

            //CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference("wad-control-container");
            //IEnumerable<IListBlobItem> blobList = cloudBlobContainer.ListBlobs();
            //IEnumerable<CloudBlobContainer> list = cloudBlobClient.ListContainers();
            //foreach (IListBlobItem item in blobList)
            //{
            //    Uri uri = item.Uri;
            //}
            //foreach (CloudBlobContainer t in list)
            //{
            //    int i = 0;
            //}

            AzureConnectDialog connectdlg = new AzureConnectDialog();
            
            connectdlg.ShowDialog();

            if (AzureConnectDialog.IsOK)
            {
                try
                {
                    AzureCommandMgr.LoadAzureDeploymentConfig();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Provide valid deployment id and storage credentials");
                    return;
                }
                RolesViewControl.DataContext = AzureMonInstanceContext.AzureApp.AppDeployment;
                IsConnected = true;
            }
            else
            {
                return;
            }
            graph = new GraphEntity();
        }

        /// <summary>
        /// Start Monitoring 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Start_MouseDown(object sender, MouseButtonEventArgs e)
        {

            if (!IsConnected)
            {
                MessageBox.Show("Connect to any azure application deployment in order to start monitoring");
                return;
            }
           

            //PerfCounter cntr1 = new PerfCounter("WorkerRole1_IN_0", "Processor", "% Privileged Time", "_Total");
            //PerfCounter cntr2 = new PerfCounter("WorkerRole1_IN_0", "Processor", "% User Time", "_Total");
            //PerfCounter cntr3 = new PerfCounter("WebRole1_IN_0", "Processor", "% Privileged Time", "_Total");
            //PerfCounter cntr4 = new PerfCounter("WebRole1_IN_0", "Processor", "% User Time", "_Total");

            //GraphSeries series1 = CreatePerformanceGraph(cntr1);
            //GraphSeries series2 = CreatePerformanceGraph(cntr2);
            //GraphSeries series3 = CreatePerformanceGraph(cntr3);
            //GraphSeries series4 = CreatePerformanceGraph(cntr4);

            //graph.GraphContext.Add(cntr1, series1);
            //graph.GraphContext.Add(cntr2, series2);
            //graph.GraphContext.Add(cntr3, series3);
            //graph.GraphContext.Add(cntr4, series4);

            timer = new DispatcherTimer();
            
            timer.Tick += new EventHandler(Refresh);

            // Set the Interval to 2 seconds (2000 milliseconds).
            timer.Interval = TimeSpan.FromSeconds(60);
            timer.IsEnabled = true;

            timer.Start();
            this.Refresh(this, null);
        }               

        /// <summary>
        /// Configure counters
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Configure_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (!IsConnected)
            {
                MessageBox.Show("Connect to any azure application deployment in order to configure monitoring");
                return;
            }
            AzMonConfig monConfig = new AzMonConfig();
            monConfig.ShowDialog();
            if (monConfig.IsOK)
            {
                AzureMonInstanceContext.AzureApp.AppDeployment[0].ApplyModifiedConfig();
            }
            else
            {
            }
            
        }

        /// <summary>
        /// Add a new graph
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Add_Grpaph_Click(object sender, MouseButtonEventArgs e)
        {
            CustomViewStackPanel.Children.Add(new GraphControl());
        }  
        
        /// <summary>
        /// Add a new role instance graph
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Add_RoleInstance_Graph_Click(object sender, MouseButtonEventArgs e)
        {
            if (!IsConnected)
            {
                MessageBox.Show("Connect to any azure application deployment in order to configure monitoring");
                return;
            }

            GraphControl newGraph = new GraphControl();
            
            if (newGraph.ConfigureGraphControl())
            {
                CustomViewStackPanel.Children.Add(newGraph);
            }
        }

        /// <summary>
        /// Add a role graph
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Add_Role_Graph_Click(object sender, MouseButtonEventArgs e)
        {
            GraphControl graph = new GraphControl();
            CustomViewStackPanel.Children.Add(graph);
        }

        
        private void RolesViewControl_Loaded(object sender, RoutedEventArgs e)
        {
        }


        private void AddCounterToGraph(object sender, MouseButtonEventArgs e)
        {
            ConfigureGraphControl(null,null);
        }


        private void AddCounterToGraph1(object sender, RoutedEventArgs e)
        {
            ConfigureGraphControl(null, null);
        }
        
        private void ConfigureGraphControl(object target, ExecutedRoutedEventArgs r)
        {
           
            GraphCounterConfig graphCntrConf = new GraphCounterConfig(graph);
            graphCntrConf.ShowDialog();
            
            if (GraphCounterConfig.IsOK)
            {
                if (null == graph)
                {
                    return;
                }
                List<PerfCounter> CntrRemove = new List<PerfCounter>();
                //List<PerfCounter> CntrAdd = new List<PerfCounter>();

                foreach (PerfCounter cntr in graph.GraphContext.Keys)
                {
                    if (!GraphCounterConfig.SelectedGraphCounters.Contains(cntr))
                    {
                        CntrRemove.Add(cntr);
                    }
                }

                foreach (PerfCounter cntr in GraphCounterConfig.SelectedGraphCounters)
                {
                    if (!graph.GraphContext.Keys.Contains(cntr))
                    {
                        GraphSeries series = CreatePerformanceGraph(cntr);
                        graph.GraphContext.Add(cntr, series);
                    }
                }

                foreach (PerfCounter cntr in CntrRemove)
                {
                    plotter.Children.Remove(graph.GraphContext[cntr].Chart);
                    graph.GraphContext.Remove(cntr);
                }
                GraphCounterConfig.SelectedGraphCounters.Clear();
                GraphCounterConfig.IsOK = false;
                
            }
            GraphCounterConfig.SelectedGraphCounters.Clear();
            GraphCounterConfig.IsOK = false;
            //r.Handled = true;
        }

        private void ConfigureGraphControlCanExecute(object target, CanExecuteRoutedEventArgs e)
        {

            e.CanExecute = true;
            e.Handled = true;
        }

        private void chkExport_Checked(object sender, RoutedEventArgs e)
        {
            //System.Windows.Forms.SaveFileDialog dialog = new System.Windows.Forms.SaveFileDialog();
            Microsoft.Win32.SaveFileDialog dialog = new Microsoft.Win32.SaveFileDialog();
            dialog.Filter = "csv files (*.csv)|*.csv|All files (*.*)|*.*";
            dialog.DefaultExt ="*.csv";
            
            if (dialog.ShowDialog().GetValueOrDefault())
            {
                if (!dialog.CheckFileExists)
                {
                    //try
                    //{
                    //    File.Create(dialog.FileName);                        
                    //}
                    //catch (Exception ex)
                    //{
                    //    MessageBox.Show("Error creating file");
                    //    Close();
                    //}
                }
                
                AzureMonInstanceContext.ExportFileLocation = dialog.FileName;
                IsExportChecked = true;
            }
            else
            {
                IsExportChecked = false;
                chkExport.IsChecked = false;
            }
        }

        private void chkExport_UnChecked(object sender, RoutedEventArgs e)
        {
            IsExportChecked = false;
            chkExport.IsChecked = false;
        }

        private void About_MouseDown(object sender, RoutedEventArgs e)
        {
            About about = new About();
            about.ShowDialog();
        }

        private void CMSMainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            
            //AzureConnectDialog connectdlg = new AzureConnectDialog();

            //connectdlg.ShowDialog();

            //if (AzureConnectDialog.IsOK)
            //{
            //    try
            //    {
            //        AzureCommandMgr.LoadAzureDeploymentConfig();
            //    }
            //    catch (Exception ex)
            //    {
            //        MessageBox.Show("Provide valid deployment id and storage credentials");
            //        return;
            //    }
            //    RolesViewControl.DataContext = AzureMonInstanceContext.AzureApp.AppDeployment;
            //    IsConnected = true;
            //}

            //graph = new GraphEntity();

            //Image im = new Image();
            
            //MenuItem item = new MenuItem();
            //item.Header = "Configure";
            //item.ToolTip = "Configure Counters";
            //item.Command = CMSCommands.Configure;
            //item.CommandTarget = plotter;
            ////item.Visibility = Visibility.Visible;
            ////item.IsVisible = true;
            ////item.IsSealed = false;
            //item.IsEnabled =true;
            
            ////item.c
            //Microsoft.Research.DynamicDataDisplay.Navigation.DefaultContextMenu menus = plotter.Children[5] as Microsoft.Research.DynamicDataDisplay.Navigation.DefaultContextMenu ;
            //menus.StaticMenuItems.Insert(0, item);
            //plotter.ContextMenu = new ContextMenu();
            //plotter.ContextMenu.ItemsSource = menus.StaticMenuItems;
            //plotter.ContextMenu.Items.Refresh();
            
            ////plotter.ContextMenu.Items.Add(item);
            ////ICommand ConfigureCommand = new RoutedUICommand("Configure","Configure",typeof(string));
            //CommandBinding binding = new CommandBinding(CMSCommands.Configure, ConfigureGraphControl, ConfigureGraphControlCanExecute);
            //plotter.CommandBindings.Add(binding);
            //plotter.Focus();
            //MenuItem FitToView = new MenuItem();
            //FitToView.Header = "Fit to view";;
            //FitToView.IsEnabled = true;
            //FitToView.Command = new RoutedUICommand("Fit to view", "Fit to view", typeof(Plotter));
            //ContextMenu menu = new ContextMenu();
            //menu.Items.Add(FitToView);
            //plotter.ContextMenu = menu;
        }
    }
    public static class CMSCommands
    {
        public static RoutedUICommand Configure
        {
            get
            {
                return CreateCommand("Configure");
            }
        }

        public static RoutedUICommand CreateCommand(string name)
        {
            return new RoutedUICommand(name, name, typeof(CMSCommands));
        }
    }
}
